{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 从零手搓中文大模型｜🚀 Day08"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "上一期介绍了`SFT`的数据准备流程，但是在正式开启`SFT`之前，我打算熟悉了解一些`SFT`的细节。\n",
    "\n",
    "大多数都是来自[互联网上资料](https://zhuanlan.zhihu.com/p/682604566)的收集整理，算是给自己留个记录，便于复习和回顾。\n",
    "\n",
    "也希望能够帮助到有需要的人。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 什么是SFT？\n",
    "\n",
    "`SFT`是`Supervised Fine-Tuning`的缩写，中文翻译为`有监督微调`。\n",
    "\n",
    "指的是在已经预训练好的模型基础上，使用有标签的数据进行微调，以适应特定的任务。\n",
    "\n",
    "在预训练模型中，由于数据量和场景的限制，模型可能无法很好地处理某些特定任务。\n",
    "\n",
    "通过有监督微调，我们可以使模型更好地适应特定场景，提高模型在特定任务上的性能。\n",
    "\n",
    "在大模型领域，我们提到`SFT`，通常指的是它一种特殊形式，即`Instruction Tuning`。\n",
    "\n",
    "接下来的内容都是基于`Instruction Tuning`来展开。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练方式\n",
    "\n",
    "在进行指令微调的时候，会将`Instruction`（指令） 以及对应的`Response`（回答）拼接成文本（具体有很多`prompt style`可以参考），然后依然以预训练时的**自回归**方式进行训练。\n",
    "\n",
    "但和预训练不同的是，在`loss`计算的时候只考虑`Response`部分，而不考虑`Instruction`部分（通过`ignore_index`来隐去）。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练数据\n",
    "\n",
    "`Meta`在论文[LIMA: Less Is More for Alignment](https://arxiv.org/abs/2305.11206)中详细地论述了一个结论：数据集的质量对微调的重要性远大于数据集的数量（即便1万的高质量数据集也能取得很好的效果，胜过10万低质量数据集）。\n",
    "\n",
    "因此我们应该花更多的时间去提升样本质量，而不是追求样本的数量。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 微调技巧"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 训练模式\n",
    "\n",
    "1. base model + domain SFT\n",
    "2. base model + domain continue pre-train + domain SFT\n",
    "3. base model + common SFT + domain SFT\n",
    "   \n",
    "上述的`base model`也都可以换成`chat model`。\n",
    "\n",
    "#### `base model` vs `chat model`\n",
    "- `base model`质量够好的时候，在base模型基础进行领域数据的SFT与在chat模型上进行SFT，效果上差异不大\n",
    "- `chat model`接`SFT`时候出现灾难性遗忘的概率比较大\n",
    "- 如果既追求领域任务的性能，又希望尽量保留通用能力，则可以考虑`base model`\n",
    "- 如果只追求领域任务的性能，则可以考虑`chat model`\n",
    "\n",
    "#### 是否`continue pre-train`\n",
    "- 如果领域任务数据集和通用数据集差异较大，则务必`continue pre-train`\n",
    "- 领域任务数据集较大且不在意通用能力而只关注领域任务，则也建议进行`continue pre-train`\n",
    "- 其他情况可以考虑不进行`continue pre-train`\n",
    "\n",
    "### 关于炼丹\n",
    "\n",
    "1. `SFT`数据集的量级如果不是特别大，建议选择较小学习率，一般设置为`pre-train`阶段学习率的10%左右。\n",
    "   \n",
    "   例如在`pre-train`阶段的学习率为`1e-5`，则`SFT`阶段的学习率设置为`1e-6`。\n",
    "\n",
    "2. `SFT`阶段建议使用比`pre-train`阶段更小的`warmup steps`，这是因为`SFT`阶段的数据量级远小于`pre-train`阶段，较小的`warmup steps`有助于模型更好地收敛。\n",
    "3. `Epoch`数量的设置和`SFT`数据的量级成反比，`SFT`数据量级越大，可以将`Epoch`数量设置越小。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "bigmodel",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.10.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
